package com.cysoft.starter.log.core.helper;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class RequestParamsHelper {

    private static final String HTTP_SERVLET_REQUEST = "HttpServletRequest";
    private static final String HTTP_SERVLET_RESPONSE = "HttpServletResponse";
    private static final String MULTIPART_FILE = "MultipartFile";

    /**
     * 获取请求参数的JSON字符串
     *
     * @param point 切入点
     * @return 请求参数的JSON字符串
     */
    public static String getRequestParams(ProceedingJoinPoint point) {
        try {
            // 获取方法的参数名
            String[] parameterNames = getParameterNames(point);
            // 获取方法的参数值
            Object[] args = point.getArgs();
            // 检查参数名或参数值是否为空或不匹配
            if (shouldReturnEmptyMap(parameterNames, args)) {
                return JSON.toJSONString(Collections.emptyMap());
            }
            // 构建参数映射
            Map<String, Object> result = buildParameterMap(parameterNames, args);
            // 将参数映射转换为JSON字符串
            return JSON.toJSONString(result);
        } catch (Exception e) {
            // 处理异常，返回空的JSON对象
            return JSON.toJSONString(Collections.emptyMap());
        }
    }

    /**
     * 获取方法的参数名
     *
     * @param point 切入点
     * @return 方法的参数名数组
     */
    private static String[] getParameterNames(ProceedingJoinPoint point) {
        return ((MethodSignature) point.getSignature()).getParameterNames();
    }

    /**
     * 检查是否应该返回空的Map
     *
     * @param parameterNames 方法的参数名数组
     * @param args           方法的参数值数组
     * @return 如果应该返回空的Map，则返回true；否则返回false
     */
    private static boolean shouldReturnEmptyMap(String[] parameterNames, Object[] args) {
        return parameterNames == null || parameterNames.length > args.length;
    }

    /**
     * 构建参数映射
     *
     * @param parameterNames 方法的参数名数组
     * @param args           方法的参数值数组
     * @return 参数映射
     */
    private static Map<String, Object> buildParameterMap(String[] parameterNames, Object[] args) {
        Map<String, Object> result = new HashMap<>();
        for (int i = 0; i < parameterNames.length; i++) {
            String paramName = parameterNames[i];
            Object object = args[i];
            result.put(paramName, getParameterValue(object));
        }
        return result;
    }

    /**
     * 根据参数类型获取参数值
     *
     * @param object 参数对象
     * @return 参数值
     */
    private static Object getParameterValue(Object object) {
        if (object instanceof HttpServletRequest) {
            return HTTP_SERVLET_REQUEST;
        } else if (object instanceof HttpServletResponse) {
            return HTTP_SERVLET_RESPONSE;
        } else if (object instanceof MultipartFile) {
            return MULTIPART_FILE;
        }
        return object;
    }

    /**
     * 拼接请求头
     * @param request
     * @return
     */
    public static String getRequestHeader(HttpServletRequest request) {
        Map<String, String> headers = new HashMap<>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            headers.put(headerName, request.getHeader(headerName));
        }
        return JSON.toJSONString(headers);
    }

    /**
     * 获取包名
     * @param point
     * @return
     */
    public static String getPackageInfo(ProceedingJoinPoint point) {
        // 获取目标对象的类
        Class<?> targetClass = point.getTarget().getClass();
        // 获取类所在的包
        Package targetPackage = targetClass.getPackage();
        // 获取包名
        return targetPackage.getName();
    }

    /**
     * 获取class信息
     * @param point
     * @return
     */
    public static String getClassInfo(ProceedingJoinPoint point) {
        Class<?> targetClass = point.getTarget().getClass();
        return targetClass.getName();
    }

    /**
     * 获取请求方法信息
     * @param point
     * @return
     */
    public static String getMethodInfo(ProceedingJoinPoint point) {
        Method method = ((MethodSignature) point.getSignature()).getMethod();
        return method.getName();
    }


}
